#ifndef _BREAK_TUPLE_
#define _BREAK_TUPLE_

#include <iostream>

namespace Break {
template <typename... Ts> struct tuple;

template <> struct tuple<> {};
using null_tuple = tuple<>;

template <typename T> struct tuple<T> : null_tuple {
public:
  tuple<T>() : value(T()) {}
  explicit tuple<T>(const T &v) : value(v) {}

public:
  T value;
};

// 递归继承  按照先入后出的顺序来保存数据
// 对于 [int, float, char]
// [int, [float, char]] : [float, [char]] : [char] : <>
template <typename T, typename... Ts> struct tuple<T, Ts...> : tuple<Ts...> {
public:
  tuple<T, Ts...>() : value(T()), tuple<Ts...>() {}

  explicit tuple<T, Ts...>(const T &v, const Ts &...args)
      : value(v), tuple<Ts...>(args...) {}

public:
  T value;
};

template <size_t Index, typename... Ts> struct g_impl;

template <size_t Index, typename T, typename... Ts>
struct g_impl<Index, tuple<T, Ts...>> {
  using value_type = typename g_impl<Index - 1, tuple<Ts...>>::value_type;
  using tuple_type = typename g_impl<Index - 1, tuple<Ts...>>::tuple_type;
};

template <typename T, typename... Ts> struct g_impl<0, tuple<T, Ts...>> {
  using value_type = T;
  using tuple_type = tuple<T, Ts...>;
};

template <> struct g_impl<0, null_tuple> {
  using value_type = null_tuple;
  using tuple_type = null_tuple;
};

template <size_t Index, typename... Ts>
typename g_impl<Index, tuple<Ts...>>::value_type &get(tuple<Ts...> &t) {
  using tuple_t = typename g_impl<Index, tuple<Ts...>>::tuple_type;
  return ((tuple_t *)&t)->value;
}

} // namespace Break

#endif // _BREAK_TUPLE_